package com.gzx.risk.core.utils;

import com.alibaba.excel.annotation.ExcelProperty;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 动态表格图片生成工具类
 * 根据实体类的@ExcelProperty注解动态生成表格列
 */
public class DynamicTableImageGenerator {

    // 样式配置
    private static final int ROW_HEIGHT = 40;
    private static final int HEADER_HEIGHT = 50;
    private static final int CELL_PADDING = 10;
    private static final int MIN_COLUMN_WIDTH = 80;
    private static final int MAX_COLUMN_WIDTH = 200;

    private static final Color HEADER_BG_COLOR = new Color(70, 130, 180);
    private static final Color HEADER_TEXT_COLOR = Color.WHITE;
    private static final Color BORDER_COLOR = new Color(200, 200, 200);
    private static final Color ODD_ROW_COLOR = new Color(248, 248, 248);
    private static final Color EVEN_ROW_COLOR = Color.WHITE;
    private static final Color TEXT_COLOR = Color.BLACK;

    private static final Font HEADER_FONT = new Font("文泉驿正黑", Font.BOLD, 14);
    private static final Font DATA_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 12);

    /**
     * 将数据列表转换为表格图片的InputStream
     */
    public static <T> InputStream convertToTableImage(List<T> dataList, Class<T> clazz) {
        try {
            BufferedImage image = createDynamicTableImage(dataList, clazz);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(image, "png", os);
            return new ByteArrayInputStream(os.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException("生成表格图片失败", e);
        }
    }

    /**
     * 创建动态表格图片
     */
    private static <T> BufferedImage createDynamicTableImage(List<T> dataList, Class<T> clazz) {
        // 1. 解析类结构，获取列信息
        List<ColumnInfo> columnInfos = parseColumnInfo(clazz);

        // 2. 计算列宽
        calculateColumnWidths(columnInfos, dataList);

        // 3. 计算图片尺寸
        int tableWidth = calculateTableWidth(columnInfos);
        int tableHeight = calculateTableHeight(dataList.size());

        // 4. 创建图片并绘制
        BufferedImage image = new BufferedImage(tableWidth, tableHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        setupGraphics(g2d);

        drawTable(g2d, columnInfos, dataList, tableWidth, tableHeight);

        g2d.dispose();
        return image;
    }

    /**
     * 解析类结构，获取列信息
     */
    private static <T> List<ColumnInfo> parseColumnInfo(Class<T> clazz) {
        List<ColumnInfo> columnInfos = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
            if (excelProperty != null) {
                String columnName = excelProperty.value()[0]; // 取第一个值作为列名
                columnInfos.add(new ColumnInfo(columnName, field.getName(), field.getType()));
            }
        }

        return columnInfos;
    }

    /**
     * 计算列宽（基于列名和数据内容）
     */
    private static <T> void calculateColumnWidths(List<ColumnInfo> columnInfos, List<T> dataList) {
        // 创建临时Graphics用于测量文本宽度
        BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
        Graphics2D tempG2d = tempImage.createGraphics();
        tempG2d.setFont(HEADER_FONT);
        FontMetrics headerMetrics = tempG2d.getFontMetrics();
        tempG2d.setFont(DATA_FONT);
        FontMetrics dataMetrics = tempG2d.getFontMetrics();

        for (ColumnInfo column : columnInfos) {
            // 测量列名宽度
            int headerWidth = headerMetrics.stringWidth(column.getColumnName()) + CELL_PADDING * 2;

            // 测量数据内容的最大宽度
            int maxDataWidth = 0;
            for (T data : dataList) {
                String cellValue = getCellValue(data, column.getFieldName());
                if (cellValue != null) {
                    int cellWidth = dataMetrics.stringWidth(cellValue) + CELL_PADDING * 2;
                    maxDataWidth = Math.max(maxDataWidth, cellWidth);
                }
            }

            // 取列名和数据中的最大宽度，并限制在最小和最大宽度之间
            int finalWidth = Math.max(headerWidth, maxDataWidth);
            finalWidth = Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, finalWidth));

            column.setWidth(finalWidth);
        }

        tempG2d.dispose();
    }

    /**
     * 获取单元格值
     */
    private static <T> String getCellValue(T data, String fieldName) {
        try {
            Field field = data.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object value = field.get(data);

            if (value == null) {
                return "";
            }

            // 特殊处理日期和百分比
            if (value instanceof LocalDate) {
                return ((LocalDate) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            } else if (value instanceof String && ((String) value).contains("%")) {
                return (String) value;
            } else {
                return value.toString();
            }
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 计算表格总宽度
     */
    private static int calculateTableWidth(List<ColumnInfo> columnInfos) {
        return columnInfos.stream().mapToInt(ColumnInfo::getWidth).sum();
    }

    /**
     * 计算表格总高度
     */
    private static int calculateTableHeight(int dataSize) {
        return HEADER_HEIGHT + dataSize * ROW_HEIGHT;
    }

    /**
     * 设置Graphics参数
     */
    private static void setupGraphics(Graphics2D g2d) {
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 设置背景
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, 5000, 5000); // 使用足够大的背景
    }

    /**
     * 绘制完整表格
     */
    private static <T> void drawTable(Graphics2D g2d, List<ColumnInfo> columnInfos,
                                      List<T> dataList, int tableWidth, int tableHeight) {
        // 绘制表头
        drawTableHeader(g2d, columnInfos);

        // 绘制数据行
        drawTableData(g2d, columnInfos, dataList);

        // 绘制表格边框
        drawTableBorders(g2d, columnInfos, dataList.size(), tableWidth, tableHeight);
    }

    /**
     * 绘制表头
     */
    private static void drawTableHeader(Graphics2D g2d, List<ColumnInfo> columnInfos) {
        g2d.setColor(HEADER_BG_COLOR);
        g2d.fillRect(0, 0, calculateTableWidth(columnInfos), HEADER_HEIGHT);

        g2d.setColor(HEADER_TEXT_COLOR);
        g2d.setFont(HEADER_FONT);

        int x = 0;
        for (ColumnInfo column : columnInfos) {
            String header = column.getColumnName();
            int width = column.getWidth();

            // 计算文本居中位置
            FontMetrics fm = g2d.getFontMetrics();
            int textWidth = fm.stringWidth(header);
            int textX = x + (width - textWidth) / 2;
            int textY = HEADER_HEIGHT / 2 + fm.getAscent() / 2 - 2;

            g2d.drawString(header, textX, textY);
            x += width;
        }
    }

    /**
     * 绘制表格数据
     */
    private static <T> void drawTableData(Graphics2D g2d, List<ColumnInfo> columnInfos, List<T> dataList) {
        g2d.setFont(DATA_FONT);

        for (int row = 0; row < dataList.size(); row++) {
            T data = dataList.get(row);

            // 设置行背景色
            if (row % 2 == 0) {
                g2d.setColor(EVEN_ROW_COLOR);
            } else {
                g2d.setColor(ODD_ROW_COLOR);
            }
            g2d.fillRect(0, HEADER_HEIGHT + row * ROW_HEIGHT,
                    calculateTableWidth(columnInfos), ROW_HEIGHT);

            // 绘制单元格数据
            g2d.setColor(TEXT_COLOR);
            int x = 0;

            for (ColumnInfo column : columnInfos) {
                String cellText = getCellValue(data, column.getFieldName());
                int width = column.getWidth();
                int y = HEADER_HEIGHT + row * ROW_HEIGHT;

                // 绘制文本
                FontMetrics fm = g2d.getFontMetrics();
                int textY = y + ROW_HEIGHT / 2 + fm.getAscent() / 2 - 2;
                int textX = x + CELL_PADDING;

                g2d.drawString(cellText, textX, textY);
                x += width;
            }
        }
    }

    /**
     * 绘制表格边框
     */
    private static void drawTableBorders(Graphics2D g2d, List<ColumnInfo> columnInfos,
                                         int rowCount, int tableWidth, int tableHeight) {
        g2d.setColor(BORDER_COLOR);
        g2d.setStroke(new BasicStroke(1));

        // 绘制外边框
        g2d.drawRect(0, 0, tableWidth - 1, tableHeight - 1);

        // 绘制列线
        int x = 0;
        for (ColumnInfo column : columnInfos) {
            x += column.getWidth();
            g2d.drawLine(x, 0, x, tableHeight);
        }

        // 绘制行线
        g2d.drawLine(0, HEADER_HEIGHT, tableWidth, HEADER_HEIGHT);
        for (int row = 1; row <= rowCount; row++) {
            int y = HEADER_HEIGHT + row * ROW_HEIGHT;
            g2d.drawLine(0, y, tableWidth, y);
        }
    }

    /**
     * 列信息内部类
     */
    private static class ColumnInfo {
        private String columnName;
        private String fieldName;
        private Class<?> fieldType;
        private int width;

        public ColumnInfo(String columnName, String fieldName, Class<?> fieldType) {
            this.columnName = columnName;
            this.fieldName = fieldName;
            this.fieldType = fieldType;
        }

        // getter and setter
        public String getColumnName() { return columnName; }
        public String getFieldName() { return fieldName; }
        public Class<?> getFieldType() { return fieldType; }
        public int getWidth() { return width; }
        public void setWidth(int width) { this.width = width; }
    }
}